import base64
import io
import os
import subprocess
import tempfile
from datetime import datetime
from typing import Any

from PIL import Image
from urllib.parse import urlparse, unquote
from pathlib import PurePosixPath


def _get_safe_filename(filename: str) -> str:
    """生成安全的文件名"""
    # 移除或替换不安全的字符
    unsafe_chars = '<>:"/\\|?*'
    for char in unsafe_chars:
        filename = filename.replace(char, '_')
    return filename


def generate_media_filename(media_type: str, description: str = None, media_id: str = None) -> str:
    """生成媒体文件名"""
    base_name = []
    if description:
        safe_desc = _get_safe_filename(description)[:50]
        base_name.append(safe_desc)

    if media_id:
        base_name.append(media_id[:10])

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    base_name.append(timestamp)

    ext_map = {
        'image': '.jpg',
        'video': '.mp4',
        'voice': '.mp3'
    }

    return f"{'_'.join(base_name)}{ext_map.get(media_type, '')}"


class MediaServer:
    def __init__(self):
        self.media_cache = {}  # {media_id: {file_path: str, timestamp: float}}
        self.cleanup_threshold = 259200  # 3天，微信临时素材有效期
        
    def add_to_cache(self, media_id: str, file_path: str):
        """添加媒体文件到缓存"""
        self.media_cache[media_id] = {
            'file_path': file_path,
            'timestamp': datetime.now().timestamp()
        }
        
    def get_from_cache(self, media_id: str) -> Any | None:
        """从缓存获取媒体文件路径"""
        if media_id in self.media_cache:
            data = self.media_cache[media_id]
            if datetime.now().timestamp() - data['timestamp'] < self.cleanup_threshold:
                return data['file_path']
            else:
                self.remove_from_cache(media_id)
        return None

    def remove_from_cache(self, media_id: str):
        """从缓存移除媒体文件"""
        if media_id in self.media_cache:
            try:
                file_path = self.media_cache[media_id]['file_path']
                if os.path.exists(file_path):
                    os.unlink(file_path)
            except Exception as e:
                print(f"清理媒体文件失败: {str(e)}")
            finally:
                del self.media_cache[media_id]

    def cleanup_expired(self):
        """清理过期的媒体文件"""
        current_time = datetime.now().timestamp()
        expired_ids = [
            media_id for media_id, data in self.media_cache.items()
            if current_time - data['timestamp'] >= self.cleanup_threshold
        ]
        for media_id in expired_ids:
            self.remove_from_cache(media_id)

    def save_media_file(self, media_type: str, file_content: bytes, description: str = None, media_id: str = None) -> str:
        """保存媒体文件"""
        try:
            base_dir = 'lucky_web/public/ai_material'
            type_dirs = {
                'video': 'ai_videos',
                'voice': 'ai_voices',
                'image': 'ai_images'
            }
            
            if media_type not in type_dirs:
                raise ValueError(f"不支持的媒体类型: {media_type}")
                
            save_dir = f'{base_dir}/{type_dirs[media_type]}'
            # 确保使用正斜杠并创建目录
            save_dir = save_dir.replace('\\', '/')
            os.makedirs(save_dir, exist_ok=True)

            file_name = generate_media_filename(media_type, description, media_id)
            # 使用 os.path.join 并确保使用正斜杠
            file_path = os.path.join(save_dir, file_name).replace('\\', '/')

            if media_id and (cached_path := self.get_from_cache(media_id)):
                if os.path.exists(cached_path):
                    return f"https://luckyzhou.online/ai_material/{type_dirs[media_type]}/{os.path.basename(cached_path)}"

            # 使用二进制写入模式
            with open(file_path, 'wb') as f:
                f.write(file_content)

            if media_id:
                self.add_to_cache(media_id, file_path)

            return f"https://luckyzhou.online/ai_material/{type_dirs[media_type]}/{file_name}"

        except Exception as e:
            print(f"保存媒体文件失败: {str(e)}")
            raise

# 创建全局MediaServer实例
media_server = MediaServer() 